#include "TestCase.h"
#include "TestFunction.h"
#include "TestFunctionInitializer.h"
#include "TestClassInitializer.h"
#include "TestException.h"
#include "TestResult.h"
#include "TestSuite.h"


TestSuite::TestSuite() 
{
}


TestSuite::TestSuite(const char *className) 
{
    addTest(className);
}


TestSuite::TestSuite(const char *className, const char *funName) 
{
    addTest(className, funName);
}


TestSuite::~TestSuite() 
{
    std::map<std::string, std::vector<std::string>*>::iterator i = _tests.begin();
    for (; i != _tests.end(); ++ i)
    {
        delete i->second;
        i->second = NULL;
    }
}


void  TestSuite::addTest(const char *className) 
{
    if (_tests.count(className) == 0)
        _tests[className] = new std::vector<std::string>;
    TestFunctionInitializer::getAllTestFunsInClass(className, _tests[className]);
}


void TestSuite:: addTest(const char *className, const char * funName) 
{
    if (_tests.count(className) == 0)
        _tests[className] = new std::vector<std::string>;
    _tests[className]->push_back(std::string(className) + "::" + std::string(funName));
}


int TestSuite::run(TestResult *tr) const
{
    std::map<std::string, std::vector<std::string>*>::const_iterator i = _tests.begin();
    for (; i != _tests.end(); ++ i)
    {
        std::string className = i->first;
        std::vector<std::string> *funs = i->second;
        TestCase* tc = TestClassInitializer::createTestCase(className);
        if (tc->setUp() != 0)
        {
            continue;
        }
      
        std::vector<std::string>::iterator j = funs->begin();
        for (; j != funs->end(); ++ j)
        {
            std::string funName = *j;
            TestFunction* tf = TestFunctionInitializer::getTestFun(funName);
            try
            {
                tf->run(tc);
            }
            catch(FailureException &fe) 
            {
                fe.setFunName(funName.c_str());
                fe.setClassName(className.c_str());
                //tr->eLog("TestException [%s]\n", fe.getAssertName());
                //printf();
                throw;
            }
        }
        if (tc->tearDown() != 0)
        {
            continue;
        }
    }
    return 0;
}
